package com.gz.gzmybatis.sqlsession;

import com.gz.gzmybatis.config.Function;
import com.gz.gzmybatis.config.MapperBean;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

//读取xml,建立连接
public class GzConfiguration {
    //类加载器
    private static ClassLoader loader=ClassLoader.getSystemClassLoader();

    //读取xml文件并处理
    public Connection build(String resource) {

        //加载gz-mybatis.xml,获得对应的inputstream
        InputStream resourceAsStream = loader.getResourceAsStream(resource);
        Connection connection=null;
        try {
            Document read = new SAXReader().read(resourceAsStream);
            //根元素 database
            Element root = read.getRootElement();
            connection=evalDataSource(root);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    //这个方法解析gz-mybatis.xml根元素，并返回Connection
    public Connection evalDataSource(Element node) {
        if (!node.getName().equals("database")) {
            throw new RuntimeException("root 应该是<database>");
        }
        String driverClassName = null;
        String url = null;
        String username = null;
        String password = null;

        for(Object item : node.elements("property")) {
            Element i=(Element)item;
            String name=i.attributeValue("name");
            String value=i.attributeValue("value");

            if(name==null||value==null) {
                throw new RuntimeException("property 结点没有设置name或value");
            }
            switch(name) {
                case "driverClassName":
                    driverClassName=value;
                    break;
                case "url":
                    url=value;
                    break;
                case "username":
                    username=value;
                    break;
                case "password":
                    password=value;
                    break;
                default:
                    throw new RuntimeException("属性名不匹配");
            }
        }

        Connection connection=null;
        try {
            Class.forName(driverClassName);
            connection = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;//返回Connection
    }

    //读取读取xxxMapper.xml,能够创建MapperBean对象
    //path就是xxxMapper.xml的路径 从类加载路径计算
    public MapperBean readMapper(String path) {
        MapperBean mapperBean = new MapperBean();
        InputStream resourceAsStream = loader.getResourceAsStream(path);
        try {
            Document read = new SAXReader().read(resourceAsStream);
            //根元素 <mapper>
            Element root = read.getRootElement();
            //得到namespace
            String namespace = root.attributeValue("namespace").trim();
            //namespace="com.gz.mapper.MonsterMapper"
            mapperBean.setInterfaceName(namespace);
            Iterator iterator = root.elementIterator();
            List<Function> list = new ArrayList<>();
            while(iterator.hasNext()) {
                Element element = (Element)iterator.next();
                Function function = new Function();
                String sqlType = element.getName().trim();
                String funcName = element.attributeValue("id").trim();
                String resultType = element.attributeValue("resultType").trim();
                String sql = element.getText().trim();
                function.setSqlType(sqlType);
                function.setFuncName(funcName);
                function.setSql(sql);
                //resultType这里是com.gz.entity.Monster，要转为实例
                Class<?> clazz = Class.forName(resultType);
                Object o = clazz.newInstance();
                function.setResultType(o);
                list.add(function);
                mapperBean.setFunctions(list);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return mapperBean;
    }
}
